/**
 * 文件名：@MethodFeatureContract.java <br/>
 * 包名：cn.efunbox.afw.soa.client.netflix.feign.support <br/>
 * 项目名：afw-soa <br/>
 * @author xtwin <br/>
 */
package cn.efunbox.afw.soa.client.netflix.feign.support;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;

import org.springframework.util.Base64Utils;
import org.springframework.util.DigestUtils;

import feign.Contract;
import feign.MethodMetadata;

/**
 * 类名：MethodFeatureContract  <br />
 *
 * 功能：根据方法特征进行请求协商
 *
 * @author xtwin <br />
 * 创建时间：2016年7月24日 下午4:11:18  <br />
 * @version 2016年7月24日
 */
public class MethodFeatureContract extends Contract.BaseContract {
	
	// 默认请求方法，默认为GET
	protected String defaultMethod = "GET";
	
	// 上下文类型
	protected String defaultContentType = "application/json;charset=UTF-8";
	
	// 请求后缀
	protected String suffix = ".json";
	
	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月24日 下午4:14:49<br/>
	 * 
	 * @param targetType
	 * @param method
	 * @return <br/>
	 * @see feign.Contract.BaseContract#parseAndValidateMetadata(java.lang.Class, java.lang.reflect.Method)
	 */
	@Override
	protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {
		MethodMetadata data = super.parseAndValidateMetadata(targetType, method);
		
		// 设置content-type
		data.template().header("Content-Type", defaultContentType);
		
		Class<?> type = method.getDeclaringClass();
		// 组装接口特征
		String signature = new StringBuilder()
				.append(type.getName())
				.append(":").append(method.getName())
				.append(":").append(Arrays.toString(method.getParameterTypes()))
				//.append(":").append("1.0.0")
			.toString();
		
		// 对template进行配置
		data.template()
			.method("POST")
			.append(toFeature(signature, data, targetType, method))
			.append(suffix);
		
		return data;
	}
	
	/**
	 * 功能： <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2016年7月24日 下午4:18:09 <br/>
	 */
	protected String toFeature(String signature, MethodMetadata data, Class<?> targetType, Method method) {
		return Base64Utils.encodeToUrlSafeString(DigestUtils.md5Digest(signature.getBytes()));
	}
	
	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月24日 下午4:13:18<br/>
	 * 
	 * @param data
	 * @param clz <br/>
	 * @see feign.Contract.BaseContract#processAnnotationOnClass(feign.MethodMetadata, java.lang.Class)
	 */
	@Override
	protected void processAnnotationOnClass(MethodMetadata data, Class<?> clz) {
		// 此处有待处理注解上定义的方法
		data.template().method(defaultMethod);
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月24日 下午4:11:40<br/>
	 * 
	 * @param data
	 * @param annotation
	 * @param method <br/>
	 * @see feign.Contract.BaseContract#processAnnotationOnMethod(feign.MethodMetadata, java.lang.annotation.Annotation, java.lang.reflect.Method)
	 */
	@Override
	protected void processAnnotationOnMethod(MethodMetadata data, Annotation annotation, Method method) {
		// 此处可供子类做扩展操作
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月24日 下午4:11:40<br/>
	 * 
	 * @param data
	 * @param annotations
	 * @param paramIndex
	 * @return <br/>
	 * @see feign.Contract.BaseContract#processAnnotationsOnParameter(feign.MethodMetadata, java.lang.annotation.Annotation[], int)
	 */
	@Override
	protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) {
		String name = String.valueOf(paramIndex);
		
		data.indexToName().put(paramIndex, Arrays.asList(name));
		
		data.formParams().add(name);
		
		return true;
	}

	/**
	 * @version 2016年7月24日-下午4:16:15
	 */
	public void setDefaultMethod(String defaultMethod) {
		this.defaultMethod = defaultMethod;
	}

	/**
	 * @version 2016年7月24日-下午4:16:15
	 */
	public void setDefaultContentType(String defaultContentType) {
		this.defaultContentType = defaultContentType;
	}
}
